package com.ztom.beans.factory

import com.ztom.beans.exception.BeansException
import com.ztom.beans.factory.support.pojo.BeanDefinition
import com.ztom.beans.factory.support.registry.BeanDefinitionRegistry
import com.ztom.util.lowercaseFirstChar
import kotlin.reflect.KClass
import kotlin.reflect.full.isSubclassOf

/**
 * BeanFactory 落地实现
 * BeanDefinitionRegistry 落地实现
 * Listable: 具有列举容器里 Bean 的能力
 *
 * @author ZhangTao
 */
class DefaultListableBeanFactory : AbstractAutowireCapableBeanFactory(),
    ConfigurableListableBeanFactory, BeanDefinitionRegistry {

    /**
     * BeanDefinitionRegistry 落地实现: 维护了 BeanDefinition 注册表
     */
    private val beanDefinitionMap = HashMap<String, BeanDefinition>()

    override fun getBeanDefinition(beanName: String): BeanDefinition {
        return beanDefinitionMap[beanName] ?: throw BeansException("No bean named '$beanName' is defined")
    }

    override fun registerBeanDefinition(beanName: String, beanDefinition: BeanDefinition) {
        beanDefinitionMap[beanName] = beanDefinition
    }

    override fun containsBeanDefinition(beanName: String): Boolean {
        return beanDefinitionMap.containsKey(beanName)
    }

    @Suppress("UNCHECKED_CAST")
    override fun <T : Any> getBeansOfType(type: KClass<out T>): Map<String, T> {
        return beanDefinitionMap.entries
            .filter { e -> e.value.beanClazz.isSubclassOf(type) }
            .associate { it.key to (getBean(it.value.beanClazz.simpleName!!.lowercaseFirstChar()) as T) }
    }

    override fun getBeanDefinitionNames(): Array<String> {
        return beanDefinitionMap.keys.toTypedArray()
    }

    override fun preInstantiateSingletons() {
        beanDefinitionMap.keys.forEach { getBean(it) }
    }
}